#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <algorithm>
#include <set>
using namespace std;

//��������
class Func
{
public:
	int operator()(int a, int b)
	{
		return a + b;
	}
};

template <typename T>
T Add(T a, T b)
{
	return a + b;
}

int main()
{
	// 2
	Func func;
	cout << func(3, 5) << endl;

	// 3
	list<int> lst = {3, 2, 5, 2, 2, 4};
	for (auto l : lst)
		cout << l << "  ";
	cout << endl;
	if (!lst.empty())
	{
		lst.front() = 6;
		lst.back() = 6;
	}
	lst.remove(2); //ɾ��list��ȫ����2
	for (auto l : lst)
		cout << l << "  ";
	cout << endl;

	// 4
	vector<int> v = {3, 2, 5, 2, 2, 4};
	auto it = v.begin();
	for (; it != v.end(); ++it)
	{
		if (!v.empty() && *it == 2)
			v.erase(it); //�������,������ʧЧ������
	}
	v.erase(remove(v.begin(), v.end(), 2), v.end()); // //remove(v.begin(), v.end(), 2); 3 5 4 2 2 4
	for (auto vv : v)
		cout << vv << "  ";
	cout << endl; //3 5 4

	//5
	vector<int> v = {3, 4, 5, 2, 1, 6};
	sort(v.begin(), v.end());
	for (auto vv : v)
		cout << vv << "  ";
	cout << endl;
	stable_partition(v.begin(), v.end(), [](int i) { return i % 2 != 0; });
	for (auto vv : v)
		cout << vv << "  ";
	cout << endl;
	partition(v.begin(), v.end(), [](int i) { return i % 2 != 0; });
	for (auto vv : v)
		cout << vv << "  ";
	cout << endl;

	//6
	set<int> nSet = {2, 0, 8, -3, -6, 56, 0, -78};
	nSet.insert(5);

	for (auto s : nSet)
		cout << s << "  ";
	cout << endl;

	//7
	vector<int> v = {-3, 2, 5, 4, -1, 6};
	sort(v.begin(), v.end());
	cout << v.front() << "  " << v.back() << endl;
	auto itMax = max_element(v.begin(), v.end());
	auto itMin = min_element(v.begin(), v.end());
	cout << *itMax << "  " << *itMin << endl;

	list<int> lst = {666, 777, 888};
	v.insert(v.end(), lst.begin(), lst.end());
	for (auto vv : v)
		cout << vv << "  ";
	cout << endl;

	//8
	int m = 22;
	int n = 10;
	cout << Add(m, n) << endl;

	return 0;
}

//shared_ptr���ʵ�֣�
template <typename T>
class Shared_ptr
{
public:
	Shared_ptr(T *p) : m_count(new int(1)), m_ptr(p) //���캯��
	{
		cout << "���캯����*m_ptr= " << *m_ptr << "  ���ü�����*m_count= " << *m_count << endl;
	}
	Shared_ptr(Shared_ptr<T> &otherptr) //�������캯��
	{
		m_count = otherptr.m_count;
		m_ptr = otherptr.m_ptr;
		++(*m_count);
		cout << "�������캯����*m_ptr= " << *m_ptr << "  ���ü�����*m_count= " << *m_count << endl;
	}
	//������ֵ�����
	Shared_ptr<T> &operator=(Shared_ptr<T> &otherptr)
	{
		++(*otherptr.m_count); //=�ұߵ����ü�����1
		if (this->m_ptr && --(*this->m_count) == 0)
		{
			delete m_count;
			delete m_ptr;
		}
		this->m_count = otherptr.m_count;
		this->m_ptr = otherptr.m_ptr;
		cout << "������ֵ�������*m_ptr= " << *m_ptr << "  ���ü�����*m_count= " << *m_count << endl;
		return *this;
	}
	//��������
	~Shared_ptr()
	{
		if (--*m_count == 0)
		{
			delete m_count;
			delete m_ptr;
			m_count = nullptr;
			m_ptr = nullptr;
		}
	}
	//�����������
	T &operator*()
	{
		return *m_ptr; //����m_ptrָ���ֵ
	}
	//��ͷ�����
	T *operator->()
	{
		return m_ptr;
	}
	bool unique()
	{
		return *m_count == 1;
	}
	size_t use_count() //������m_ptr�������������ָ�������
	{
		return *m_count;
	}
	void swap(Shared_ptr &ptr)
	{
		std::swap(*this, ptr);
	}

private:
	int *m_count; //ָ�����ü�����ָ��
	T *m_ptr;
};
//��Ķ��������ⲻ�ܷ������˽�г�Ա����

/* unique_ptrʹ�ó�����
1��Ϊ��̬�������Դ�ṩ�쳣��ȫ��֤
2�����غ����ڶ�̬������Դ������Ȩ
3���������б���ָ��
4��������̬����
5����Ϊauto_ptr�����Ʒ
*/

//ɾ����
template <typename T>
class DefaultDeleter
{
	void operator()(T *ptr) const
	{
		delete ptr;
		ptr = nullptr;
	}
};

template <typename T, typename Deleter = DefaultDeleter<T>>
class Unique_ptr
{
public:
	//����
	Unique_ptr(T *ptr = nullptr, const Deleter &de = Deleter()) : m_uptr(ptr), m_deleter(de)
	{
		cout << "���캯����*m_uptr= " << *m_uptr << endl;
	}
	~Unique_ptr() //����
	{
		del();
	}
	//����ɾ����
	void del()
	{
		m_deleter(m_uptr);
		m_uptr = nullptr;
	}

	//��֧����ͨ�Ŀ����븳ֵ
	Unique_ptr(const Unique_ptr &) = delete;
	Unique_ptr &operator=(const Unique_ptr &) = delete;

	//��unique_ptrָ��ָ������һ��ָ��
	void reset(T *ptr)
	{
		del();
		m_uptr = ptr;
		cout << "����reset" << endl;
	}
	//�ͷŶ�ָ��Ŀ���Ȩ������ָ�룬��unique_ptr�ÿ�
	T *release()
	{
		T *ptr = m_uptr;
		m_uptr = nullptr;
		cout << "����release" << endl;
		return ptr;
	}

	T &operator*()
	{
		return *m_uptr;
	}
	T *operator->()
	{
		return m_uptr;
	}

private:
	T *m_uptr;
	Deleter m_deleter;
};

int main()
{
	Unique_ptr<int> up1(new int(1));
	*up1 = 100;
	cout << *up1 << endl;
	auto p2 = up1.release();
	Unique_ptr<int> up3(new int(3));
	int *pf, a = 100;
	pf = &a;
	up3.reset(pf);
	return 0;
}